Inherited Widgets Explained - Flutter Widgets 101 Ep. 3:
Youtube 地址:https://youtu.be/Zbm3hjPjQMk
InheritedWidget (Flutter Widget of the Week):
Youtube 地址:https://youtu.be/1t-8rBCGBYw
我们在编写代码时,通过 Widget 的嵌套,创建了一个 Widget Tree,当嵌套的层级变得复杂的时候,那么跨层级获取数据也就变的困难起来,你得在每一层的构造方法中添加一个属性,用于传递数据。
Flutter 自然不会允许这种情况存在,作为万物皆 Widget 的它,自然也会有一个功能性的 Widget 来处理这种情况,那就是:InheritedWidget 。
使用起来也很简单:
创建要 InheritedWidget 的子类:
class ShareDataWidget extends InheritedWidget{ }
按照提示重写其
updateShouldNotify
方法,顾名思义,该方法是定义“当数据发生更新时是否发出通知”,一般情况下当数据发生变化发出通知,但也有例外,例如当更新的数据和原本的数据相同,则不发出通知,所以我们一般这样写:@override bool updateShouldNotify(ShareDataWidget oldWidget) { return oldWidget.shareData != shareData; }
在上面的代码中的
shareData
就是我们想要共享的数据,所以我们也需要对这个数据做出定义:class ShareDataWidget extends InheritedWidget{ int shareData; ShareDataWidget({this.shareData, Widget child}) : super(child: child); ...... }
最后一步,还需要提供一个外界可以直接访问共享对象的方法:
class ShareDataWidget extends InheritedWidget{ ...... static ShareDataWidget getShareData(BuildContext context) { return context.inheritFromWidgetOfExactType(ShareDataWidget); } }
至此,一个共享数据的 Widget 就创建完成了,它该如何使用?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
int count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: new Center(
child: ShareDataWidget(
shareData: count,
child: new Column(
children: <Widget>[
ChildWidget(),
new MaterialButton(
color: Colors.lightGreenAccent,
onPressed: () {
count++;
setState(() {});
},
child: Text("+"),
),
],
),
),
),
);
}
}
class ChildWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return ChildWidgetState();
}
}
class ChildWidgetState extends State<ChildWidget> {
@override
Widget build(BuildContext context) {
int data = ShareDataWidget.getShareData(context).shareData;
return Text(
"$data",
style: TextStyle(fontSize: 50),
);
}
}
class ShareDataWidget extends InheritedWidget {
final int shareData;
ShareDataWidget({this.shareData, Widget child}) : super(child: child);
@override
bool updateShouldNotify(ShareDataWidget oldWidget) {
return oldWidget.shareData != shareData;
}
static ShareDataWidget getShareData(BuildContext context) {
return context.inheritFromWidgetOfExactType(ShareDataWidget);
}
}
在上面的例子中,点击 MyApp 中的按钮,其属性 count 发生变化,同时其子控件 ChildWidget 也会收到更新通知,随着发生变化,修改 UI,同时子控件的 didChangeDependencies
回调也会被调用(代码中没有展示)。